package dog.weatherwallpaper.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.URL;

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.NetworkInfo;
import dog.weatherwallpaper.R;

public class Internet {
	private static final String IP = "http://www.icanhazip.com";
	private static final String WWO = "http://api.worldweatheronline.com/free/v1/";
	private static final String WEATHER = WWO + "weather.ashx";
	private static final String LOCATION = WWO + "search.ashx";
	private static final String DROPBOX = "https://dl.dropboxusercontent.com/u/39767058/";
	private static final String VERSION = DROPBOX + "version";
	private static final String APK_URL = DROPBOX + "WeatherWallpaper.apk";
	public static final String APK_FILE = "update.apk";

	/**
	 * Indicates whether network connectivity exists and it is possible to establish connections and pass data.
	 * DOES NOT CHECK INTERNET ACCESS.
	 * 
	 * @return true if network connectivity exists, false otherwise.
	 */
	public boolean isConnected() {
		NetworkInfo ni = App.getConnectivityManager().getActiveNetworkInfo();
		return ni != null && ni.isConnected();
	}

	/**
	 * Get public IP address (empty String if not connected).
	 */
	public String getIP() {
		return readURLContent(IP);
	}

	/**
	 * Gets JSON string with location info. Returns null if <b>ip</b> is null or empty.
	 */
	public String getLocation(final String ip) {
		if (Strings.isNullOrEmpty(ip)) { return null; }
		return readURLContent(getLocationQuery(ip));
	}

	/**
	 * Gets JSON string with weather info. Returns null if <b>ip</b> is null or empty.
	 */
	public String getWeather(final String ip) {
		if (Strings.isNullOrEmpty(ip)) { return null; }
		return readURLContent(getWeatherQuery(ip));
	}

	public int getVersion() {
		return Strings.tryParse(readURLContent(VERSION));
	}

	/**
	 * Downloads the app
	 * 
	 * @return true if downloaded successfully
	 */
	@SuppressLint({ "WorldReadableFiles", "WorldWriteableFiles" })
	public boolean downloadAPK() {
		File file = new File(APK_FILE);
		if (file.exists()) {
			file.delete();
		}
		try {
			@SuppressWarnings("deprecation")
			OutputStream fos = App.context().openFileOutput(APK_FILE,
					Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
			new DefaultHttpClient().execute(new HttpGet(APK_URL)).getEntity().writeTo(fos);
			fos.close();
			return true;
		} catch (Exception e) {
			App.sendMail(e);
			return false;
		}
	}

	private String readURLContent(final String spec) {
		try {
			URL url = new URL(spec);
			InputStream is;
			try {
				is = url.openConnection().getInputStream();
			} catch (IOException e) {
				// no internet access
				return null;
			}

			Reader isr = new InputStreamReader(is);
			BufferedReader reader = new BufferedReader(isr);
			String line = reader.readLine();
			reader.close();
			isr.close();
			is.close();
			return line;
		} catch (IOException e) {
			App.sendMail(e);
			return null;
		}
	}

	private String getLocationQuery(final String ip) {
		StringBuilder sb = new StringBuilder();
		sb.append(LOCATION);
		sb.append("?query=");
		sb.append(ip);
		sb.append("&format=json");
		sb.append("&num_of_results=1");
		sb.append("&key=");
		sb.append(readAPIKey());
		return sb.toString();
	}

	private String getWeatherQuery(final String location) {
		StringBuilder sb = new StringBuilder();
		sb.append(WEATHER);
		sb.append("?q=");
		sb.append(location.replace(' ', '+'));
		sb.append("&format=json");
		sb.append("&num_of_days=5");
		sb.append("&key=");
		sb.append(readAPIKey());
		return sb.toString();
	}

	/**
	 * File wwo.key is missing because World Weather Online requires that the API key remains private.
	 */
	private String readAPIKey() {
		String key = null;
		InputStream is = App.context().getResources().openRawResource(R.raw.wwo);
		Reader isr = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(isr);
		try {
			key = br.readLine();
			br.close();
		} catch (IOException e) {
			App.sendMail(e);
		}
		return key;
	}
}